﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Documents;
using PSE.Deployment.ConfigurationManager.Controls;
using PSE.Deployment.SetupBase;
using PSE.Deployment.SetupBase.Parameter.Enums;
using PSE.Deployment.SetupBase.UI;
using PSE.Deployment.Util;
using Sinacor.Deployment.Setup.DataAccess;
using Sinacor.Deployment.Setup.Main;
using Sinacor.Deployment.Setup.Parameter;
using Sinacor.Deployment.Setup.UI.CustomComponents;

namespace Sinacor.Deployment.Setup.UI
{
    public partial class CompanySelection : BaseWizardWindow
    {
        #region Propriedades
        public Parameter.DataBaseConnection ConnectionInfo { get; set; }
        public ObservableCollection<CompanyVersion> CompaniesVersions { get; set; }
        #endregion

        #region Construtor
        public CompanySelection()
        {
            this.InitializeComponent();

            this.ConnectionInfo = SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo;

            this.CompaniesVersions = new ObservableCollection<CompanyVersion>();

            this.DataContext = this;

            this.AllowNext = true;

            AddCompanies();
        }
        #endregion

        #region Eventos e Métodos CheckBox "EMPRESAS"
        private void ChkCompany_Click(object sender, RoutedEventArgs e)
        {
            SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = false;
            SetCompanies();
        }

        private void SetCompanies()
        {
            foreach (SinacorSetupCheckBox chkCompany in TrvCompany.Items)
            {
                chkCompany.IsChecked = ChkCompany.IsChecked;

                if (chkCompany.IsChecked.GetValueOrDefault())
                    AddCompanyVersion(chkCompany);
                else
                    RemoveCompanyVersion(chkCompany);

            }

        }
        #endregion

        #region Método Add Companies
        private void AddCompanies()
        {
            TrvCompany.Items.Clear();

            using (OracleDataBase db = new OracleDataBase(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.User, EncryptDecrypt.Decrypt(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.Password), SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.TNSName, SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.IsEncrypted))
            {
                StringBuilder sqlCommand = new StringBuilder();

                sqlCommand.Append("SELECT DISTINCT E.CD_EMPRESA, E.NM_EMPRESA, E.CD_USUA_ORAC FROM TGEEMPR E INNER JOIN TGESINST I ON E.CD_EMPRESA = I.CD_EMPRESA");

                using (IDataReader dr = db.ExecuteReader(sqlCommand.ToString()))
                {
                    while (dr.Read())
                    {
                        SinacorSetupCheckBox chkCompany = new SinacorSetupCheckBox();
                        chkCompany.Content = dr.GetString(2) + " ( " + dr.GetString(1) + " )" + " ( " + dr.GetInt32(0).ToString() + " )";
                        CompanyValue companyValue = new CompanyValue();
                        companyValue.Id = dr.GetInt32(0);
                        companyValue.Login = dr.GetString(2);
                        companyValue.Name = dr.GetString(2) + " ( " + dr.GetString(1) + " )" + " ( " + dr.GetInt32(0).ToString() + " )";
                        chkCompany.Value = companyValue;
                        chkCompany.Click += new RoutedEventHandler(chkCompanies_Click);
                        chkCompany.IsChecked = ((SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Find(x => x.Id == companyValue.Id) != null) || (SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Find(x => x.Id == companyValue.Id) != null));
                        companyValue.Status = PrerequisitesStatus.NotOk;

                        if (chkCompany.IsChecked.GetValueOrDefault())
                        {
                            AddCompanyVersion(chkCompany);
                            ChkCompany.IsChecked = true;
                        }

                        TrvCompany.Items.Add(chkCompany);
                    }
                }
            }

        }
        #endregion

        #region Eventos e Métodos CheckBox das Companias
        void chkCompanies_Click(object sender, RoutedEventArgs e)
        {
            SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = false;

            SetCompanyCheckBox();

            SinacorSetupCheckBox chk = (SinacorSetupCheckBox)sender;
            if (chk.IsChecked.Value)
                AddCompanyVersion(chk);
            else
                RemoveCompanyVersion(chk);

        }

        private void SetCompanyCheckBox()
        {
            bool anyChecked = false;

            foreach (SinacorSetupCheckBox company in TrvCompany.Items)
            {
                if (company.IsChecked.GetValueOrDefault())
                {
                    anyChecked = true;
                    break;
                }
            }

            ChkCompany.IsChecked = anyChecked;
        }

        private void AddCompanyVersion(SinacorSetupCheckBox chk)
        {
            foreach (Configuration.VersionInfo versionInfo in SetupMainFactory.GetInstance<SinacorMain>().Configuration.DataBase.Versions)
            {
                StringBuilder sqlCommand = new StringBuilder();
                sqlCommand.Append("Select VS_SIST_INST from TGESINST Where CD_EMPRESA = :CodEmpresa And CD_SISTEMA = :CodSistema");

                using (OracleDataBase db = new OracleDataBase(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.User, EncryptDecrypt.Decrypt(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.Password), SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.TNSName, SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.IsEncrypted))
                {
                    List<DataBaseParameter> dataBaseParameter = new List<DataBaseParameter>();
                    CompanyValue companyValue = (CompanyValue)chk.Value;

                    DataBaseParameter paramEmpresa = new DataBaseParameter("CodEmpresa", companyValue.Id);
                    DataBaseParameter paramSistema = new DataBaseParameter("CodSistema", versionInfo.Module.Id.ToUpper());

                    dataBaseParameter.Add(paramEmpresa);
                    dataBaseParameter.Add(paramSistema);

                    IDataReader dr = db.ExecuteReader(sqlCommand.ToString(), dataBaseParameter);

                    string dataBaseVersion = string.Empty;

                    if (dr.Read())
                        dataBaseVersion = dr.GetString(0);

                    if (!string.IsNullOrEmpty(dataBaseVersion))
                    {
                        CompanyVersion version = new CompanyVersion();

                        version.Company.Id = companyValue.Id;
                        version.Company.Login = companyValue.Login;
                        version.Company.Name = chk.Content.ToString();
                        version.Company.DataBaseVersion = dataBaseVersion;
                        version.Company.Module.Id = versionInfo.Module.Id;
                        version.Company.Module.Name = versionInfo.Module.Name;
                        version.SetupVersions = SetupMainFactory.GetInstance<SinacorMain>().Configuration.DataBase.Versions.Find(v => v.Module.Id == versionInfo.Module.Id).Versions;
                        version.ExtendedSetupVersions = GetExtendedSetupVersion(version.SetupVersions);

                        if (version.SetupVersions.Contains(version.Company.DataBaseVersion))
                        {
                            version.Status = PrerequisitesStatus.Ok;
                            version.Company.Status = PrerequisitesStatus.Ok;
                            companyValue.Status = PrerequisitesStatus.Ok;
                        }
                        else
                        {
                            if (companyValue.Status == PrerequisitesStatus.Ok)
                                companyValue.Status = PrerequisitesStatus.Warning;

                            version.Company.Status = PrerequisitesStatus.NotOk;
                            version.Status = PrerequisitesStatus.NotOk;
                        }

                        version.ToolTipMessage = GetCompanyToolTipMessage(version.Status);

                        this.CompaniesVersions.Add(version);
                    }
                }
            }

        }

        private void RemoveCompanyVersion(SinacorSetupCheckBox chk)
        {
            CompanyValue companyValue = (CompanyValue)chk.Value;

            for (int i = CompaniesVersions.Count - 1; i >= 0; i--)
            {
                if (CompaniesVersions[i].Company.Id == companyValue.Id)
                {
                    CompaniesVersions.RemoveAt(i);

                }
            }
        }
        #endregion

        #region Métodos de Apoio
        private string GetExtendedSetupVersion(List<string> Versions)
        {
            string extendedSetupVersion = String.Empty;

            foreach (string version in Versions)
            {
                extendedSetupVersion += version + ", ";
            }

            if (extendedSetupVersion != string.Empty)
                extendedSetupVersion = extendedSetupVersion.Substring(0, extendedSetupVersion.Length - 2);

            return extendedSetupVersion;
        }

        private string GetCompanyToolTipMessage(PrerequisitesStatus status)
        {
            string toolTipMessage = String.Empty;

            switch (status)
            {
                case PrerequisitesStatus.Ok:
                    toolTipMessage = "Versão compatível";
                    break;
                case PrerequisitesStatus.NotOk:
                    toolTipMessage = "Versão incompatível. " + Environment.NewLine + "Algumas funcionalidades não funcionarão adequadamente para este módulo.";
                    break;
            }

            return toolTipMessage;
        }

        private string GetCompaniesNames(List<Company> companies)
        {
            string companiesNames = string.Empty;

            foreach (Company company in companies)
            {
                companiesNames += company.Name + " (" + company.Login + ")" + Environment.NewLine;
            }

            return companiesNames;
        }

        private string GetModuleNames()
        {
            string companiesNames = string.Empty;

            var modules = CompaniesVersions.Where(c => c.Status == PrerequisitesStatus.NotOk).Distinct(new CompanyVersionComparer());

            foreach (CompanyVersion module in modules)
            {
                companiesNames += module.Company.Module.Name + " (";

                foreach (CompanyVersion company in CompaniesVersions.Where(c => c.Company.Module.Id == module.Company.Module.Id))
                {
                    if (company.Company.Status == PrerequisitesStatus.NotOk)
                    {
                        companiesNames += +company.Company.Id + ", ";
                    }
                }

                if (companiesNames.EndsWith(", "))
                    companiesNames = companiesNames.Substring(0, companiesNames.Length - 2);

                companiesNames += ")" + Environment.NewLine;
            }

            return companiesNames;
        }
        #endregion

        #region Eventos botões Próximo e Anterior
        protected override void OnNextClick(RoutedEventArgs e)
        {
            base.OnNextClick(e);
            SetSelectedCompanies();

            if (SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Count > 0 &&
                SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Count == 0)
            {
                SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = false;
                ConfigurationMessageBox.Show("Não será possível utilizar as empresas listadas abaixo pois não estão compatíveis com a versão deste setup." + Environment.NewLine + Environment.NewLine + GetCompaniesNames(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed), "Atenção", ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Exclamation);
                e.Handled = true;
            }
            else if (SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Count > 0 &&
                     SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Count > 0)
            {
                if (!SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies && ConfigurationMessageBox.Show("Não será possível utilizar as empresas listadas abaixo pois não estão compatíveis com a versão deste setup." + Environment.NewLine + "Deseja prosseguir com a instalação das demais empresas?" + Environment.NewLine + Environment.NewLine + GetCompaniesNames(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed), "Atenção", ConfigurationMessageBoxButton.YesNo, ConfigurationMessageBoxImage.Question) == ConfigurationMessageBoxResult.No)
                {
                    SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = false;
                    e.Handled = true;
                }
                else
                    SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = true;
            }
            else if (SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Count == 0 &&
                     SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Count > 0 &&
                     SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Any(c => c.Status == PrerequisitesStatus.Warning))
            {
                if (!SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies && ConfigurationMessageBox.Show("Os módulos abaixo não estão compatíveis com a versão deste setup e algumas funcionalidades poderão não funcionar adequadamente." + Environment.NewLine + "Deseja prosseguir com a instalação?" + Environment.NewLine + Environment.NewLine + GetModuleNames(), "Atenção", ConfigurationMessageBoxButton.YesNo, ConfigurationMessageBoxImage.Exclamation) == ConfigurationMessageBoxResult.No)
                {
                    SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = false;
                    e.Handled = true;
                }
                else
                    SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.PermitedCompatibleCompanies = true;
            }
        }

        protected override void OnPreviousClick(RoutedEventArgs e)
        {
            base.OnPreviousClick(e);
            SetSelectedCompanies();
        }

        #endregion

        #region Método Salvar Empresas Selecionadas
        private void SetSelectedCompanies()
        {
            SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Clear();
            SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Clear();

            foreach (SinacorSetupCheckBox item in TrvCompany.Items)
            {
                if (item.IsChecked.GetValueOrDefault())
                {
                    CompanyValue itemValue = (CompanyValue)item.Value;

                    Parameter.Company company = new Parameter.Company();
                    company.Id = itemValue.Id;
                    company.Login = itemValue.Login;
                    company.Name = itemValue.Name;
                    company.Status = itemValue.Status;

                    if (itemValue.Status == PrerequisitesStatus.NotOk)
                        SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.CompaniesNotAllowed.Add(company);
                    else
                        SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.Companies.Add(company);

                }
            }

        }
        #endregion

    }

    public class CompanyVersion
    {
        public CompanyVersion()
        {
            this.Company = new Company();
            this.SetupVersions = new List<string>();
        }

        public Parameter.Company Company { get; set; }
        public List<string> SetupVersions { get; set; }
        public string ExtendedSetupVersions { get; set; }
        public PrerequisitesStatus Status { get; set; }
        public string ToolTipMessage { get; set; }
    }

    public class CompanyValue
    {
        public int Id { get; set; }
        public string Login { get; set; }
        public string Name { get; set; }
        public PrerequisitesStatus Status { get; set; }

        public CompanyValue()
        {
            Status = PrerequisitesStatus.Ok;
        }
    }

    public class CompanyVersionComparer : IEqualityComparer<CompanyVersion>
    {
        public bool Equals(CompanyVersion x, CompanyVersion y)
        {
            return x.Company.Module.Name == x.Company.Module.Id;
        }

        public int GetHashCode(CompanyVersion obj)
        {
            return (obj.Company.Module.Id + obj.Company.Module.Name).GetHashCode();
        }
    }
}
